package ExcelTools

import (
	"ToolLibray/jwtx"
	"ToolLibray/pinyin"
	"bytes"
	"context"
	"fmt"
	"github.com/xuri/excelize/v2"
	"github.com/zeromicro/go-zero/core/logx"
	"math"
	"mime/multipart"
	"property_api/internal/svc"
	"property_api/internal/types"
	"property_api/utils/xform"
	"property_service/property_service"
	"strconv"
	"strings"
	"sync"
	"time"
)

type UploadLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

type CombinedAssetInfo struct {
	AssetBasicInfo   *types.AssetBasicInfo   //资产基础信息
	ChartOfAccount   ChartOfAccountList      //财务科目
	FundSource       FundSourceList          //资金来源
	DepreciationInfo *types.DepreciationInfo //折旧信息
	TenderInfo       *types.TenderInfo       //招标信息
}

type ChartOfAccountList struct {
	//固定资产科目ID（如果多使用部门用;分割）
	FixedAssetSubjects string
	//累计折旧科目ID（如果多使用部门用;分割）
	DepreciationSubjects string
	//科目ID（如果多使用部门用;分割）
	SubjectName string
	//科目使用科室名称（如果多使用部门用;分割）
	UsageRoom string
	//占比（如果多使用部门用;分割）
	Percentage string
}

type FundSourceList struct {
	//自有资金（如果多使用部门用;分割）
	SourceAmount1 string
	//财政基本拨款（如果多使用部门用;分割）
	SourceAmount2 string
	//科教费用（如果多使用部门用;分割）
	SourceAmount3 string
	//财政项目拨款（如果多使用部门用;分割）
	SourceAmount4 string
	//其他（如果多使用部门用;分割）
	SourceAmount5 string
	//资金使用科室名称（如果多使用部门用;分割）
	UsageRoom2 string
}

func NewUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadLogic {
	return &UploadLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

/*
*
上传数据，添加到数据库
*/
func (l *UploadLogic) Upload(file *multipart.FileHeader, sheetName string, stockID int64) (resp *types.ResponseByte, err error) {
	// 定义数据解析函数映射
	dataParsers := map[string]func([]string) (interface{}, error){
		//-------------------需处理层级关系--------------------
		//财务科目
		"财务科目": func(row []string) (interface{}, error) {
			return ParseFinanceAccountSubject(row)
		},
		//科室
		"科室": func(row []string) (interface{}, error) {
			return ParseHospitalDepartment(row)
		},
		//资产分类
		"资产分类": func(row []string) (interface{}, error) {
			return ParseAssetCategory(row)
		},

		//-------------------无层级关系--------------------
		//资产信息
		"资产信息": func(row []string) (interface{}, error) {
			return ParseAssetBasicInfo(row)
		},
		//厂商信息
		"厂商信息": func(row []string) (interface{}, error) {
			return ParseVendorInfo(row)
		},
		//资产类型
		"资产类型": func(row []string) (interface{}, error) {
			return ParseAssetType(row)
		},
		//品牌信息
		"品牌信息": func(row []string) (interface{}, error) {
			return ParseBrandAddition(row)
		},
		//产地信息
		"产地信息": func(row []string) (interface{}, error) {
			return ParseOriginAddition(row)
		},
		//财务分类
		"财务分类": func(row []string) (interface{}, error) {
			return ParseAssetFinancialCategory(row)
		},
		//供应商级别
		"供应商": func(row []string) (interface{}, error) {
			return ParseSupplierLevelAddition(row)
		},

		// 可以添加其他表的数据解析函数
	}

	// 使用 background context，不依赖 HTTP 请求上下文
	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 1200*time.Second) // 设置足够长的超时时间
	defer cancel()

	// l.Logger.Infof("开始处理Excel上传，表名: %s", sheetName)

	// 获取数据解析函数
	dataParser, ok := dataParsers[sheetName]
	if !ok {
		l.Logger.Errorf("不支持的表名: %s", sheetName)
		return nil, fmt.Errorf("不支持的表名: %s", sheetName)
	}

	// 调用公共方法解析 Excel 数据
	parsedData, err := ParseExcelData(file, sheetName, dataParser)
	if err != nil {
		return nil, err
	}

	// l.Logger.Infof("解析Excel数据完成，共%d条记录", len(parsedData))

	lens := 0
	//科目编码出问题的
	var YcCode []string
	//父级编码不存在的
	var DoesNotExist []string
	//父级编码长度超过两个的
	var ExceedTwo []string
	// 设置租户ID，从上下文中获取
	tenantID := jwtx.GetUserTenantId64(l.ctx)
	// 设置创建用户和更新用户，从上下文中获取
	userIdStr := xform.Int64ToString(jwtx.GetUserId(l.ctx))
	MesBug := ""
	//问题数组
	var Msgs []string

	// l.Logger.Infof("开始处理数据，租户ID: %d, 用户ID: %s", tenantID, userIdStr)

	// 根据表名处理转换后的数据
	switch sheetName {
	case "资产信息":
		//转换为组合结构体
		var combinedList []*CombinedAssetInfo
		//转换为组合结构体
		for _, item := range parsedData {
			combinedList = append(combinedList, item.(*CombinedAssetInfo))
		}
		//处理以后的数组（批量新增）
		var AssetBasicInfos []*property_service.AssetBasicInfo
		//获取基础状态
		stat, err := l.svcCtx.BasicService.StatusDispositionPage(l.ctx, &property_service.StatusDispositionPageReq{
			Page:  0,
			Limit: 0,
			Where: &property_service.StatusDisposition{
				TenantID:    tenantID,
				StatusGroup: "asset_basic_info", //状态组
				Status:      "1",                //状态为启用
			},
		})
		if err != nil {
			l.Logger.Error("状态查询失败", err)
			Msgs = append(Msgs, fmt.Sprintf(" %s 状态查询失败：%v", Msgs, err.Error()))
			return nil, err
		} else if len(stat.List) != 1 {
			l.Logger.Error("查询状态数据异常", len(combinedList))
			Msgs = append(Msgs, fmt.Sprintf(" %s 查询状态数据异常：%v", Msgs, err.Error()))
			return nil, err
		}
		//分批处理，调用多线程处理数据，获取返回集合
		if len(combinedList) < 250 {
			//数量少则不进行多线程处理
			// l.Logger.Infof("数据量较少(%d条)，不使用多线程处理", len(combinedList))
			Msgs, AssetBasicInfos = l.DuoXian(0, stockID, tenantID, ctx, combinedList, stat.List[0])
		} else if len(combinedList) > 250 {
			//将数组分成四个分组
			// 2. 获取多少线程 300的倍数
			n := len(combinedList) / 300
			// l.Logger.Infof("======================共:%d条数据   启动: %d 条线程==============", len(combinedList), n)
			// 3. 计算每份大小
			total := len(combinedList)
			batch := total / n
			if total%n != 0 {
				batch++ // 向上取整，保证全量覆盖
			}
			var wg sync.WaitGroup
			// 3. 分批处理
			for i := 0; i < n; i++ {
				start := i * batch
				end := start + batch
				if end > total {
					end = total
				}
				wg.Add(1)

				// 3. 启动 goroutine
				i := i
				go func(threadNo, s, e int) {
					defer wg.Done()
					l.Logger.Infof("启动goroutine %d，处理数据范围[%d, %d)", threadNo, s, e)
					// 4. 切片传进去：共享底层数组，零拷贝
					Msgx, AssetBasicInfox := l.DuoXian(s, stockID, tenantID, ctx, combinedList[s:e], stat.List[0])
					Msgs = append(Msgs, Msgx...)
					AssetBasicInfos = append(AssetBasicInfos, AssetBasicInfox...)
					l.Logger.Infof("goroutine %d完成，处理了%d条错误信息和%d条资产信息", threadNo, len(Msgx), len(AssetBasicInfox))
				}(i, start, end)
			}
			wg.Wait()
			l.Logger.Info("全部goroutine处理完成")
			// l.Logger.Infof("Msgs长度:%d, AssetBasicInfos长度:%d", len(Msgs), len(AssetBasicInfos))
		}

		//将有问题的储存起来
		if len(Msgs) > 0 {
			l.Logger.Error("存在数据问题，共%d条", len(Msgs))
			//將MesBug转为txt输出
			// 将字符串写入文件
			var buf bytes.Buffer
			for _, s := range Msgs {
				buf.WriteString(s)
				buf.WriteByte('\n')
			}
			return &types.ResponseByte{
				Code:    404,
				Data:    buf.Bytes(),
				Message: fmt.Sprintf("数据存在问题，保存数据错误"),
			}, nil
		} else {
			//设置成功数据
			lens = len(AssetBasicInfos)
		}
		//如果不存在问题，则添加数据

	case "供应商":
		var financeSubjects []*types.SupplierLevelAddition
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.SupplierLevelAddition))
		}
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("处理第%d条供应商数据: %s", i+1, x.SupplierLevelName)
			//添加数据导入
			// 调用服务层方法，添加财务科目记录
			_, err := l.svcCtx.BasicService.SupplierLevelAdditionAdd(ctx, &property_service.SupplierLevelAddition{
				SupplierLevelName: x.SupplierLevelName,                          // 供应商级别名称
				PronunciationCode: pinyin.ToPinyinInitials(x.SupplierLevelName), // 拼音简码
				SupplierPerson:    x.SupplierPerson,                             //供应商人
				SupplierPhone:     x.SupplierPhone,                              //供应商电话
				Address:           x.Address,                                    //供应商地址
				Remark:            x.Remark,                                     // 备注
				TenantID:          tenantID,                                     // 租户ID
				CreatedAtuser:     userIdStr,                                    // 创建用户
				UpdatedAtuser:     userIdStr,                                    // 更新用户
			})
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:供应商数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
		}
	case "财务分类":
		var financeSubjects []*types.AssetFinancialCategory
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.AssetFinancialCategory))
		}
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("处理第%d条财务分类数据: %s", i+1, x.CategoryName)
			//添加数据导入
			// 调用服务层方法，添加财务科目记录
			_, err := l.svcCtx.BasicService.AssetFinancialCategoryAdd(ctx, &property_service.AssetFinancialCategory{
				CategoryCode: x.CategoryCode, // 分类编码
				CategoryName: x.CategoryName, //
				// 分类名称
				PronunciationCode: x.PronunciationCode, //拼音简码
				Remark:            x.Remark,            //备注
				TenantID:          tenantID,            // 租户ID
				CreatedAtuser:     userIdStr,           // 创建用户
			})
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:财务分类数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
		}
	case "资产类型":
		//获取集合
		var financeSubjects []*types.AssetType
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.AssetType))
		}

		var data []map[string]interface{}
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("处理第%d条资产类型数据: %s", i+1, x.Name)
			//添加数据导入
			//如果SubjectCode已存在则不能添加，跳过此次循环
			//如果不是0则代表数据异常
			if l.GetLength("asset_type", "code", x.Code, tenantID) != 0 {
				// l.Logger.Infof("资产类型编码已存在: %s", x.Code)
				//异常编码
				YcCode = append(YcCode, x.Code)
				//跳过此次添加
				continue
			}
			// 调用服务层方法，添加资产类型
			res, err := l.svcCtx.BasicService.AssetTypeAdd(ctx, &property_service.AssetType{
				Name:               x.Name, //资产类型名称
				Code:               x.Code, //资产类型编码
				Remark:             x.Remark,
				ParentCode:         x.ParentCode,                    // 父级编码(将编码转换为id)
				PinyinCode:         pinyin.ToPinyinInitials(x.Name), // 科目编码
				DepreciationPeriod: x.DepreciationPeriod,            // 折旧年限
				TenantID:           tenantID,                        // 租户ID
				UpdatedAtuser:      userIdStr,                       // 创建人
				CreatedAtuser:      userIdStr,                       // 创建人
			})
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:资产类型数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
			// l.Logger.Infof("成功添加资产类型: %s, ID: %d", x.Name, res.Id)
			if x.ParentCode != "" {
				dataItem := map[string]interface{}{
					"ID":         res.Id,
					"ParentCode": x.ParentCode,
				}
				data = append(data, dataItem)
			}
			// l.Logger.Infof("创建成功,id为:%d", res.Id)
		}
		// l.Logger.Infof("成功条数%d, 总共需要处理父级%d", lens, len(data))
		//将已有的父级编码的进行查询修改
		if len(data) > 0 {
			//将有问题的字符串则显示
			for i, row := range data {
				//当前ID
				// l.Logger.Infof("处理第%d个父级关系, 当前id%d", i+1, row["ID"])
				// l.Logger.Infof("父级编码:%s", row["ParentCode"].(string))
				// 创建一个带有超时的 context
				data, _ := l.svcCtx.BasicService.AssetTypePage(ctx, &property_service.AssetTypePageReq{
					Page:  0,
					Limit: 0,
					Where: &property_service.AssetType{
						TenantID: tenantID,
						//查询编码
						Code: row["ParentCode"].(string),
					},
				})
				//如果数组长度大于零
				if data.Count > 0 {
					//找到的数组，大于两串表示长度不对
					if data.Count == 1 {
						//找到父级编码并且赋值
						//修改值
						_, err := l.svcCtx.CustomizeService.Upz(ctx, &property_service.JudgmentConditions{
							TableName:       "asset_type",
							JudgmentField:   "id",
							JudgmentValue:   fmt.Sprintf("%d", row["ID"].(int64)),
							AssignmentField: "parent_id",
							Assignment:      xform.Int64ToString(data.List[0].ID),
							TenantID:        tenantID,
						})
						// 如果服务层返回错误，返回统一的错误响应
						if err != nil {
							l.Logger.Errorf("保存第%d数据错误:资产类型数据报错: %v", i, err.Error())
							return &types.ResponseByte{
								Code:    0,
								Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
						}
					} else {
						fmt.Printf("数组长度异常")
						//数组长度异常
						ExceedTwo = append(ExceedTwo, row["ParentCode"].(string))
					}
				} else {
					fmt.Printf("未找到父级编码的")
					//未找到父级编码的
					DoesNotExist = append(DoesNotExist, row["ParentCode"].(string))
				}
			}
		}
	case "品牌信息":
		var financeSubjects []*types.BrandAddition
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.BrandAddition))
		}
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("开始处理第%d条品牌信息数据: %s", i+1, x.BrandName)
			//添加数据导入
			// 调用服务层方法，添加财务科目记录
			_, err := l.svcCtx.BasicService.BrandAdditionAdd(ctx, &property_service.BrandAddition{
				BrandName:         x.BrandName,                          // 品牌名称
				PronunciationCode: pinyin.ToPinyinInitials(x.BrandName), // 拼音简码
				Manufacturer:      x.Manufacturer,                       // 生产厂家
				Phone:             x.Phone,                              // 电话
				Address:           x.Address,                            // 地址
				Website:           x.Website,                            // 网址
				ContactPerson:     x.ContactPerson,                      // 联系人
				TenantID:          tenantID,                             // 租户ID
				CreatedAtuser:     userIdStr,                            // 创建用户
			})
			// l.Logger.Infof("完成处理第%d条品牌信息数据: %s", i+1, x.BrandName)
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:品牌信息数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
		}
		// l.Logger.Infof("品牌信息数据处理完成，共处理%d条数据", len(financeSubjects))
	case "产地信息":
		var financeSubjects []*types.OriginAddition
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.OriginAddition))
		}
		//将id储存进来，用来循环更改
		for _, x := range financeSubjects {
			//添加数据导入
			// 调用服务层方法，添加财务科目记录
			_, err := l.svcCtx.BasicService.OriginAdditionAdd(ctx, &property_service.OriginAddition{
				OriginName:        x.OriginName,                          // 产地名称
				PronunciationCode: pinyin.ToPinyinInitials(x.OriginName), // 拼音简码
				ImportFlag:        x.ImportFlag,                          // 进口标识
				Remark:            x.Remark,                              // 备注
				TenantID:          tenantID,                              // 租户ID
				CreatedAtuser:     userIdStr,                             // 创建用户
			})
			lens = lens + 1
			if err != nil {
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
		}
	case "厂商信息":
		var financeSubjects []*types.VendorInfo
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.VendorInfo))
		}
		//将id储存进来，用来循环更改
		for _, x := range financeSubjects {
			//添加数据导入
			// 调用服务层方法，添加财务科目记录
			_, err := l.svcCtx.BasicService.VendorInfoAdd(ctx, &property_service.VendorInfo{
				Name:          x.Name,          // 厂商名称
				UnifiedCode:   x.UnifiedCode,   // 统一社会信用代码
				ContactPerson: x.ContactPerson, // 联系人
				ContactPhone:  x.ContactPhone,  // 联系电话
				VendorType:    x.VendorType,    // 厂商类型
				Province:      x.Province,      // 省份
				City:          x.City,          // 城市
				Address:       x.Address,       // 公司地址
				Remark:        x.Remark,        // 备注
				TenantID:      tenantID,        // 租户ID
				CreatedAtuser: userIdStr,       // 创建用户
			})
			lens = lens + 1
			if err != nil {
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
		}
	case "财务科目":
		var financeSubjects []*types.FinanceAccountSubject
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.FinanceAccountSubject))
		}

		var data []map[string]interface{}
		//将id储存进来，用来循环更改
		//totalCount := len(financeSubjects)
		for i, x := range financeSubjects {
			// l.Logger.Infof("处理第%d/%d条财务科目数据: %s", i+1, totalCount, x.SubjectName)

			//添加数据导入
			//如果SubjectCode已存在则不能添加，跳过此次循环
			//如果不是0则代表数据异常
			if l.GetLength("finance_account_subject", "subject_code", x.SubjectCode, tenantID) != 0 {
				l.Logger.Errorf("财务科目编码已存在，跳过: %s", x.SubjectCode)
				//异常编码
				YcCode = append(YcCode, x.SubjectName)
				//跳过此次添加
				continue
			}
			// 调用服务层方法，添加财务科目记录
			res, err := l.svcCtx.BasicService.FinanceAccountSubjectAdd(ctx, &property_service.FinanceAccountSubject{
				ParentCode:       x.ParentCode,       // 父级编码(将编码转换为id)
				SubjectCode:      x.SubjectCode,      // 科目编码
				SubjectName:      x.SubjectName,      // 科目名称
				BalanceDirection: x.BalanceDirection, // 余额方向
				SubjectType:      x.SubjectType,      // 科目类型
				TenantID:         tenantID,           // 租户ID
				UpdatedAtuser:    userIdStr,          // 创建人
				CreatedAtuser:    userIdStr,          // 创建人
			})
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:财务科目数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
			if x.ParentCode != "" {
				dataItem := map[string]interface{}{
					"ID":         res.Id,
					"ParentCode": x.ParentCode,
				}
				data = append(data, dataItem)
			}
			// l.Logger.Infof("创建财务科目成功, ID为: %d, 名称: %s", res.Id, x.SubjectName)
		}
		// l.Logger.Infof("财务科目数据处理完成，成功条数: %d, 需要处理父级关系: %d", lens, len(data))

		//将已有的父级编码的进行查询修改
		if len(data) > 0 {
			// l.Logger.Infof("开始处理父级关系，共%d条", len(data))
			//将有问题的字符串则显示
			for i, row := range data {
				//当前ID
				// l.Logger.Infof("处理第%d/%d条父级关系, 当前ID: %d, 父级编码: %s",
				//	i+1, len(data), row["ID"], row["ParentCode"].(string))

				// 创建一个带有超时的 context
				data, _ := l.svcCtx.BasicService.FinanceAccountSubjectPage(ctx, &property_service.FinanceAccountSubjectPageReq{
					Page:  0,
					Limit: 0,
					Where: &property_service.FinanceAccountSubject{
						TenantID: tenantID,
						//查询编码
						SubjectCode: row["ParentCode"].(string),
					},
				})
				//如果数组长度大于零
				if data.Count > 0 {
					//找到的数组，大于两串表示长度不对
					if data.Count == 1 {
						//找到父级编码并且赋值
						// l.Logger.Infof("找到父级科目: %s, ID: %d", data.List[0].SubjectName, data.List[0].ID)
						//修改值
						_, err := l.svcCtx.CustomizeService.Upz(ctx, &property_service.JudgmentConditions{
							TableName:       "finance_account_subject",
							JudgmentField:   "id",
							JudgmentValue:   fmt.Sprintf("%d", row["ID"].(int64)),
							AssignmentField: "parent_id",
							Assignment:      xform.Int64ToString(data.List[0].ID),
							TenantID:        tenantID,
						})
						// 如果服务层返回错误，返回统一的错误响应
						if err != nil {
							l.Logger.Errorf("更新父级关系报错: %v", err)
							return &types.ResponseByte{
								Code:    0,
								Message: fmt.Sprintf("保存第%d数据错误:报错%s", i, err.Error())}, nil
						}
						// l.Logger.Infof("更新父级关系成功, ID: %d -> ParentID: %d", row["ID"].(int64), data.List[0].ID)
					} else {
						l.Logger.Errorf("查询到多个父级编码，数组长度异常: %s", row["ParentCode"].(string))
						fmt.Printf("数组长度异常")
						//数组长度异常
						ExceedTwo = append(ExceedTwo, row["ParentCode"].(string))
					}
				} else {
					l.Logger.Errorf("未找到父级编码: %s", row["ParentCode"].(string))
					fmt.Printf("未找到父级编码的")
					//未找到父级编码的
					DoesNotExist = append(DoesNotExist, row["ParentCode"].(string))
				}
			}
			// l.Logger.Infof("父级关系处理完成")
		}
	case "科室":
		//科室表
		var financeSubjects []*types.HospitalDepartment
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.HospitalDepartment))
		}

		var data []map[string]interface{}
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("处理第%d条科室数据: %s, 编码: %s", i+1, x.Name, x.DepartmentCode)

			//添加数据导入
			//如果SubjectCode已存在则不能添加，跳过此次循环
			//如果不是0则代表数据异常
			if l.GetLength("hospital_department", "department_code", x.DepartmentCode, tenantID) != 0 {
				l.Logger.Errorf("科室编码已存在，跳过: %s", x.DepartmentCode)
				//异常编码
				YcCode = append(YcCode, x.Name)
				//跳过此次添加
				continue
			}
			// 调用服务层方法，添加财务科目记录
			res, err := l.svcCtx.BasicService.HospitalDepartmentAdd(ctx, &property_service.HospitalDepartment{
				ParentID:          x.ParentID,                      // 父级ID
				ParentCode:        x.ParentCode,                    //父级编码
				ParentLs:          x.ParentLs,                      // 父级列表
				DepartmentCode:    x.DepartmentCode,                // 科室编号
				HisDepartmentCode: x.HisDepartmentCode,             // HIS科室编码
				Name:              x.Name,                          // 科室名称
				DepartmentType:    x.DepartmentType,                // 科室类型
				PinyinCode:        pinyin.ToPinyinInitials(x.Name), // 拼音简码
				Director:          x.Director,                      // 科室负责人
				MaintenanceAuto:   x.MaintenanceAuto,               // 维修自动处理
				Status:            1,                               // 状态
				StatusName:        "开启",                            //状态名称
				Remark:            x.Remark,                        // 备注
				StockID:           stockID,                         // 仓库ID
				TenantID:          tenantID,                        // 租户ID
				CreatedAtuser:     userIdStr,                       // 创建用户
				UpdatedAtuser:     userIdStr,                       // 更新用户
			})
			lens = lens + 1
			if err != nil {
				l.Logger.Errorf("保存第%d数据错误:科室数据报错: %v", i, err)
				return &types.ResponseByte{
					Code:    0,
					Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
			}
			// l.Logger.Infof("成功添加科室: %s, ID: %d", x.Name, res.Id)

			if x.ParentCode != "" {
				dataItem := map[string]interface{}{
					"ID":         res.Id,
					"ParentCode": x.ParentCode,
				}
				data = append(data, dataItem)
			}
		}

		//将已有的父级编码的进行查询修改
		if len(data) > 0 {
			// l.Logger.Infof("开始处理科室父级关系，共%d条", len(data))
			//将有问题的字符串则显示
			for i, row := range data {
				//当前ID
				// l.Logger.Infof("处理第%d/%d条父级关系, 当前ID: %d, 父级编码: %s",
				//i+1, len(data), row["ID"], row["ParentCode"].(string))

				data, _ := l.svcCtx.BasicService.HospitalDepartmentPage(ctx, &property_service.HospitalDepartmentPageReq{
					Page:  0,
					Limit: 0,
					Where: &property_service.HospitalDepartment{
						TenantID: tenantID,
						//查询编码
						DepartmentCode: row["ParentCode"].(string),
					},
				})
				//如果数组长度大于零
				if data.Count > 0 {
					//找到的数组，大于两串表示长度不对
					if data.Count == 1 {
						//找到父级编码并且赋值
						// l.Logger.Infof("找到父级科室: %s, ID: %d", data.List[0].Name, data.List[0].ID)
						//修改值
						_, err := l.svcCtx.CustomizeService.Upz(ctx, &property_service.JudgmentConditions{
							TableName:       "hospital_department",
							JudgmentField:   "id",
							JudgmentValue:   fmt.Sprintf("%d", row["ID"].(int64)),
							AssignmentField: "parent_id",
							Assignment:      xform.Int64ToString(data.List[0].ID),
							TenantID:        tenantID,
						})
						// 如果服务层返回错误，返回统一的错误响应
						if err != nil {
							l.Logger.Errorf("更新科室父级关系报错: %v", err)
							return &types.ResponseByte{
								Code:    0,
								Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
						}
						// l.Logger.Infof("更新科室父级关系成功, ID: %d -> ParentID: %d", row["ID"].(int64), data.List[0].ID)
					} else {
						l.Logger.Errorf("查询第%d数据错误:到多个父级编码，数组长度异常: %s", i, row["ParentCode"].(string))
						//数组长度异常
						ExceedTwo = append(ExceedTwo, row["ParentCode"].(string))
					}
				} else {
					l.Logger.Errorf("未找到第%d数据错误:父级编码: %s", i, row["ParentCode"].(string))
					//未找到父级编码的
					DoesNotExist = append(DoesNotExist, row["ParentCode"].(string))
				}
			}
			// l.Logger.Infof("科室父级关系处理完成")
		}
		// l.Logger.Infof("科室数据处理完成，共处理%d条数据", len(financeSubjects))
	case "资产分类":
		//资产分类表
		var financeSubjects []*types.AssetCategory
		for _, item := range parsedData {
			financeSubjects = append(financeSubjects, item.(*types.AssetCategory))
		}
		var data []map[string]interface{}
		var succ []*types.AssetCategory
		//将id储存进来，用来循环更改
		for i, x := range financeSubjects {
			// l.Logger.Infof("开始处理第%d条资产分类数据: %s, 编码: %s", i+1, x.Name, x.CategoryCode)

			//定义报错
			var erms string
			//添加数据导入
			//如果category_code已存在则不能添加，跳过此次循环
			//如果不是0则代表数据异常
			if l.GetLength("asset_category", "category_code", x.CategoryCode, tenantID) != 0 {
				l.Logger.Errorf("资产分类编码已存在，跳过: %s", x.CategoryCode)
				//异常编码
				YcCode = append(YcCode, x.Name)
				//拼接报错
				erms = fmt.Sprintf("编码已存在")
			}
			//查询财务分类
			//如果不为空
			if len(x.FinancialCategoryName) != 0 {
				idd, er := l.ChaXunFinanceAccountSubject(x.FinancialCategoryName, tenantID)
				if er != "" {
					//报错
					erms = fmt.Sprintf(" %s 财务分类:  %s", erms, er)
					l.Logger.Errorf("查询财务分类出错: %s, 分类名: %s", er, x.FinancialCategoryName)
				} else {
					x.FinancialCategoryID = idd
					// l.Logger.Infof("查询到财务分类ID: %d, 分类名: %s", idd, x.FinancialCategoryName)
				}
			}
			//查询资产类型
			//如果不为空
			if len(x.AssetTypeName) != 0 {
				idd, er := l.ChaXunAssetType(x.AssetTypeName, tenantID)
				if er != "" {
					//报错
					erms = fmt.Sprintf(" %s 资产类型:  %s", erms, er)
					l.Logger.Errorf("查询资产类型出错: %s, 类型名: %s", er, x.AssetTypeName)
				} else {
					x.AssetTypeID = idd.ID
					// l.Logger.Infof("查询到资产类型ID: %d, 类型名: %s", idd.ID, x.AssetTypeName)
				}
			}

			//查询厂商信息
			//如果不为空
			if len(x.ManufacturerName) != 0 {
				idd, er := l.ChaXunSupplierCertType(x.ManufacturerName, tenantID)
				if er != "" {
					//报错
					erms = fmt.Sprintf(" %s 厂商信息:  %s", erms, er)
					l.Logger.Errorf("查询厂商信息出错: %s, 厂商名: %s", er, x.ManufacturerName)
				} else {
					x.ManufacturerID = idd
					// l.Logger.Infof("查询到厂商信息ID: %d, 厂商名: %s", idd, x.ManufacturerName)
				}
			}
			if erms == "" || len(erms) == 0 {
				succ = append(succ, x)
				// l.Logger.Infof("第%d条资产分类数据验证通过: %s", i+1, x.Name)
			} else {
				erms = fmt.Sprintf("第 %d 资产分类: %s 出现问题 %s", i+1, x.Name, erms)
				Msgs = append(Msgs, erms)
				l.Logger.Errorf("第%d条资产分类数据验证失败: %s, 错误: %s", i+1, x.Name, erms)
			}
		}
		//导入出现报错
		if len(Msgs) > 0 {
			l.Logger.Errorf("资产分类数据验证存在错误，共%d条", len(Msgs))
			//將MesBug转为txt输出
			// 将字符串写入文件
			var buf bytes.Buffer
			for _, s := range Msgs {
				buf.WriteString(s)
				buf.WriteByte('\n')
			}
			return &types.ResponseByte{
				Code:    404,
				Data:    buf.Bytes(),
				Message: fmt.Sprintf("数据存在问题，保存数据错误"),
			}, nil
		} else {
			// l.Logger.Infof("资产分类数据验证通过，开始批量添加，共%d条", len(succ))
			//如果没出现问题，批量添加数据
			for i, x := range succ {
				// l.Logger.Infof("处理第%d/%d条资产分类数据: %s", i+1, len(succ), x.Name)
				// 调用服务层方法，添加财务科目记录
				res, err := l.svcCtx.BasicService.AssetCategoryAdd(ctx, &property_service.AssetCategory{
					ParentID:              x.ParentID,                      // 父级ID
					ParentCode:            x.ParentCode,                    //父级编码
					ParentLs:              x.ParentLs,                      // 父级列表
					CategoryCode:          x.CategoryCode,                  // 分类编号
					CustomCodeFlag:        x.CustomCodeFlag,                // 编号规则
					Name:                  x.Name,                          // 分类名称
					PinyinCode:            pinyin.ToPinyinInitials(x.Name), // 拼音简码
					DepreciationMonths:    x.DepreciationMonths,            // 折旧年限
					ManufacturerID:        x.ManufacturerID,                // 生产厂商ID
					ManufacturerName:      x.ManufacturerName,              // 生产厂商名称
					FinancialCategoryID:   x.FinancialCategoryID,           // 财务分类id
					FinancialCategoryName: x.FinancialCategoryName,         // 财务分类名称
					BrandID:               x.BrandID,                       // 品牌id
					BrandName:             x.BrandName,                     // 品牌名称
					Status:                1,                               // 状态
					StatusName:            x.StatusName,                    // 状态名称
					UnitPrice:             x.UnitPrice,                     // 单价
					Unit:                  x.Unit,                          // 单位
					IsComponent:           x.IsComponent,                   // 部件标志
					NeedMaintenance:       x.NeedMaintenance,               // 预防性维护
					Remark:                x.Remark,                        // 备注
					StockID:               stockID,                         // 仓库ID
					TenantID:              tenantID,                        // 租户ID
					CreatedAtuser:         userIdStr,                       // 创建用户
					AssetTypeID:           x.AssetTypeID,                   //资产类型id
					AssetTypeName:         x.AssetTypeName,                 //资产类型名称
				})
				lens = lens + 1
				if err != nil {
					l.Logger.Errorf("保存第%d数据错误:资产分类数据报错: %v", i, err)
					return &types.ResponseByte{
						Code:    0,
						Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
				}
				// l.Logger.Infof("成功添加资产分类: %s, ID: %d", x.Name, res.Id)
				if x.ParentCode != "" {
					dataItem := map[string]interface{}{
						"ID":         res.Id,
						"ParentCode": x.ParentCode,
					}
					data = append(data, dataItem)
				}
			}
		}

		//将已有的父级编码的进行查询修改
		if len(data) > 0 {
			// l.Logger.Infof("开始处理资产分类父级关系，共%d条", len(data))
			//将有问题的字符串则显示
			for i, row := range data {
				//当前ID
				// l.Logger.Infof("处理第%d/%d条父级关系, 当前ID: %d, 父级编码: %s",
				//i+1, len(data), row["ID"], row["ParentCode"].(string))

				data, _ := l.svcCtx.BasicService.AssetCategoryPage(ctx, &property_service.AssetCategoryPageReq{
					Page:  0,
					Limit: 0,
					Where: &property_service.AssetCategory{
						TenantID: tenantID,
						//查询编码
						CategoryCode: row["ParentCode"].(string),
					},
				})
				//如果数组长度大于零
				if data.Count > 0 {
					//找到的数组，大于两串表示长度不对
					if data.Count == 1 {
						//找到父级编码并且赋值
						// l.Logger.Infof("找到父级资产分类: %s, ID: %d", data.List[0].Name, data.List[0].ID)
						//修改值
						_, err := l.svcCtx.CustomizeService.Upz(ctx, &property_service.JudgmentConditions{
							TableName:       "asset_category",
							JudgmentField:   "id",
							JudgmentValue:   fmt.Sprintf("%d", row["ID"].(int64)),
							AssignmentField: "parent_id",
							Assignment:      xform.Int64ToString(data.List[0].ID),
							TenantID:        tenantID,
						})
						// 如果服务层返回错误，返回统一的错误响应
						if err != nil {
							l.Logger.Errorf("更新资产分类父级关系报错: %v", err)
							return &types.ResponseByte{
								Code:    0,
								Message: fmt.Sprintf("保存数据报错%s%s", "", err.Error())}, nil
						}
						// l.Logger.Infof("更新资产分类父级关系成功, ID: %d -> ParentID: %d", row["ID"].(int64), data.List[0].ID)
					} else {
						l.Logger.Errorf("查询到第%d数据错误:多个父级编码，数组长度异常: %s", i, row["ParentCode"].(string))
						fmt.Printf("数组长度异常")
						//数组长度异常
						ExceedTwo = append(ExceedTwo, row["ParentCode"].(string))
					}
				} else {
					l.Logger.Errorf("未找到第%d数据错误:父级编码: %s", i, row["ParentCode"].(string))
					fmt.Printf("未找到父级编码的")
					//未找到父级编码的
					DoesNotExist = append(DoesNotExist, row["ParentCode"].(string))
				}
			}
			// l.Logger.Infof("资产分类父级关系处理完成")
		}
		// l.Logger.Infof("资产分类数据处理完成，共处理%d条数据", len(financeSubjects))
	}
	var ms = ""
	if len(YcCode) > 0 {
		ms = fmt.Sprintf(",科目编码:  %s 存在异常问题", strings.Join(YcCode, ","))
	}
	if len(ExceedTwo) > 0 || len(DoesNotExist) > 0 {
		msg := ""
		mssg := ""
		if len(ExceedTwo) > 0 {
			//如果大于0
			msg = fmt.Sprintf("	,父级编码超过两个: %s", strings.Join(ExceedTwo, ","))
		}
		if len(DoesNotExist) > 0 {
			//如果大于0
			mssg = fmt.Sprintf("	,父级编码未找到: %s", strings.Join(DoesNotExist, ","))
		}
		MesBug = fmt.Sprintf("%s%s", msg, mssg)
	}
	// l.Logger.Infof("当前导入条数: %d", lens)
	if lens > 0 {
		return &types.ResponseByte{Code: 200, Message: fmt.Sprintf("导入成功，已导入至表: %s ,共计条数: %d 条数据%s%s", sheetName, lens, ms, MesBug)}, nil
	} else {
		return &types.ResponseByte{Code: 0, Message: fmt.Sprintf("未保存数据%s%s", ms, MesBug)}, nil
	}
}

// 公共方法获取数组长度
func (l *UploadLogic) GetLength(TableName string, JudgmentField string, JudgmentValue string, TenantID int64) (length int64) {
	// 创建一个带有超时的 context
	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 600*time.Second) // 添加超时控制
	defer cancel()
	www, err := l.svcCtx.CustomizeService.CxLength(ctx, &property_service.JudgmentConditions{
		TableName:       TableName,
		JudgmentField:   JudgmentField,
		JudgmentValue:   JudgmentValue,
		AssignmentField: "",
		Assignment:      "",
		TenantID:        TenantID,
	})
	// 数据异常
	if err != nil {
		return 1
	}
	//获取长度并返回
	return www.Id
}

// ParseExcelData 解析 Excel 文件并返回转换后的数据切片
/*
ParseExcelData 函数用于解析Excel文件中的数据
参数:
    file: multipart.FileHeader类型的文件头信息
    sheetName: 要解析的Excel工作表名称
    dataParser: 自定义的数据解析函数，用于将每行数据解析为目标类型
返回值:
    []interface{}: 解析后的数据切片
    error: 错误信息，如果解析过程中出现错误则返回非nil值
*/
func ParseExcelData(file *multipart.FileHeader, sheetName string, dataParser func(row []string) (interface{}, error)) ([]interface{}, error) {
	// 获取文件
	openFile, err := file.Open()
	if err != nil {
		return nil, err
	}
	defer openFile.Close()

	// 使用 excelize 读取 Excel 文件
	f, err := excelize.OpenReader(openFile)
	if err != nil {
		return nil, err
	}

	// 获取所有行数据
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, err
	}

	// 定义一个切片来存储转换后的数据
	var parsedData []interface{}

	// 记录总行数
	totalRows := len(rows)
	logx.Infof("开始解析Excel数据，工作表: %s, 总行数: %d", sheetName, totalRows)

	// 遍历每一行数据
	for i, row := range rows {
		// 跳过表头
		if i == 0 {
			logx.Infof("跳过表头行")
			continue
		}

		// 解析每一行数据
		parsedItem, err := dataParser(row)
		if err != nil {
			logx.Errorf("第 %d 行数据解析失败: %v", i+1, err)
			return nil, fmt.Errorf("第 %d 行数据解析失败: %v", i+1, err)
		}

		// 将解析后的数据添加到切片
		parsedData = append(parsedData, parsedItem)

		// 每处理100行记录一次日志
		if (i+1)%100 == 0 || i == totalRows-1 {
			logx.Infof("已解析 %d/%d 行数据", i, totalRows-1)
		}
	}

	logx.Infof("Excel数据解析完成，成功解析 %d 条记录", len(parsedData))
	return parsedData, nil
}

// 获取数组并返回字符串，字符拼接
// ParseFinanceAccountSubject 解析财务科目数据
func ParseFinanceAccountSubject(row []string) (*types.FinanceAccountSubject, error) {
	// 创建 FinanceAccountSubject 实例
	financeAccountSubject := &types.FinanceAccountSubject{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			financeAccountSubject.ParentCode = field
		case 1:
			financeAccountSubject.SubjectCode = field
		case 2:
			financeAccountSubject.SubjectName = field
		case 3:
			if field != "" {
				balanceDirection, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("余额方向转换错误：%v", err)
				}
				financeAccountSubject.BalanceDirection = balanceDirection
			}
		case 4:
			financeAccountSubject.SubjectType = field
		}
	}

	return financeAccountSubject, nil
}

// ParseHospitalDepartment 解析科室数据
func ParseHospitalDepartment(row []string) (*types.HospitalDepartment, error) {
	fmt.Println("长度：", len(row), row)
	// 创建 HospitalDepartment 实例
	hospitalDepartment := &types.HospitalDepartment{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			hospitalDepartment.ParentCode = field
		case 1:
			hospitalDepartment.DepartmentCode = field
		case 2:
			hospitalDepartment.Name = field
		case 3:
			hospitalDepartment.DepartmentType = field
		case 4:
			hospitalDepartment.Director = field
		case 5:
			hospitalDepartment.MaintenanceAuto = field
		case 6:
			hospitalDepartment.Remark = field
		}

	}

	return hospitalDepartment, nil
}

// ParseAssetCategory 解析资产分类数据
func ParseAssetCategory(row []string) (*types.AssetCategory, error) {
	// 创建 AssetCategory 实例
	assetCategory := &types.AssetCategory{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			assetCategory.ParentCode = field
		case 1:
			assetCategory.CategoryCode = field
		case 2:
			assetCategory.Name = field
		case 3:
			if field != "" {
				depreciationMonths, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("折旧年限转换错误：%v", err)
				}
				assetCategory.DepreciationMonths = int32(depreciationMonths)
			}
		case 4:
			assetCategory.ManufacturerName = field
		case 5:
			assetCategory.BrandName = field
		case 6:
			if field != "" {
				unitPrice, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("单价转换错误：%v", err)
				}
				assetCategory.UnitPrice = unitPrice
			}
		case 7:
			assetCategory.Unit = field
		case 8:
			assetCategory.IsComponent = field
		case 9:
			assetCategory.NeedMaintenance = field
		case 10:
			assetCategory.Remark = field
		case 11:
			assetCategory.AssetTypeName = field
		}
	}

	return assetCategory, nil
}

// ParseVendorInfo 解析厂商信息数据
func ParseVendorInfo(row []string) (*types.VendorInfo, error) {
	// 创建 VendorInfo 实例
	vendorInfo := &types.VendorInfo{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			vendorInfo.Name = field
		case 1:
			vendorInfo.UnifiedCode = field
		case 2:
			vendorInfo.ContactPerson = field
		case 3:
			vendorInfo.ContactPhone = field
		case 4:
			vendorInfo.VendorType = field
		case 5:
			vendorInfo.Province = field
		case 6:
			vendorInfo.City = field
		case 7:
			vendorInfo.Address = field
		case 8:
			vendorInfo.Remark = field
		}
	}

	return vendorInfo, nil
}

// ParseAssetType 解析资产类型数据
func ParseAssetType(row []string) (*types.AssetType, error) {
	// 创建 AssetType 实例
	assetType := &types.AssetType{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			assetType.Code = field
		case 1:
			assetType.Name = field
		case 2:
			assetType.ParentCode = field
		case 3:
			if field != "" {
				depreciationPeriod, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("资产折旧年限转换错误：%v", err)
				}
				assetType.DepreciationPeriod = depreciationPeriod
			}
		case 4:
			assetType.Remark = field
		}
	}

	return assetType, nil
}

// ParseBrandAddition 解析品牌信息数据
func ParseBrandAddition(row []string) (*types.BrandAddition, error) {
	// 创建 BrandAddition 实例
	brandAddition := &types.BrandAddition{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			brandAddition.BrandName = field
		case 1:
			brandAddition.PronunciationCode = field
		case 2:
			brandAddition.Manufacturer = field
		case 3:
			brandAddition.Phone = field
		case 4:
			brandAddition.Address = field
		case 5:
			brandAddition.Website = field
		case 6:
			brandAddition.ContactPerson = field
		}
	}

	return brandAddition, nil
}

// ParseOriginAddition 解析产地附加信息数据
func ParseOriginAddition(row []string) (*types.OriginAddition, error) {
	// 创建 OriginAddition 实例
	originAddition := &types.OriginAddition{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			originAddition.OriginName = field
		case 1:
			originAddition.PronunciationCode = field
		case 2:
			originAddition.ImportFlag = field
		case 3:
			originAddition.Remark = field
		}
	}

	return originAddition, nil
}

// ParseAssetFinancialCategory 解析资产财务分类数据
func ParseAssetFinancialCategory(row []string) (*types.AssetFinancialCategory, error) {
	// 创建 AssetFinancialCategory 实例
	assetFinancialCategory := &types.AssetFinancialCategory{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			assetFinancialCategory.CategoryCode = field
		case 1:
			assetFinancialCategory.CategoryName = field
		case 2:
			assetFinancialCategory.PronunciationCode = field
		case 3:
			assetFinancialCategory.Remark = field
		}
	}

	return assetFinancialCategory, nil
}

// ParseSupplierLevelAddition 解析供应商级别信息数据
func ParseSupplierLevelAddition(row []string) (*types.SupplierLevelAddition, error) {
	// 创建 SupplierLevelAddition 实例
	supplierLevelAddition := &types.SupplierLevelAddition{}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			supplierLevelAddition.SupplierLevelName = field
		case 1:
			supplierLevelAddition.SupplierPerson = field
		case 2:
			supplierLevelAddition.SupplierPhone = field
		case 3:
			supplierLevelAddition.Remark = field
		case 4:
			supplierLevelAddition.Address = field
		}
	}

	return supplierLevelAddition, nil
}

// ParseAssetBasicInfo 解析资产信息数据
func ParseAssetBasicInfo(row []string) (interface{}, error) {
	// 创建 combined 实例
	combined := &CombinedAssetInfo{
		AssetBasicInfo:   &types.AssetBasicInfo{},
		ChartOfAccount:   ChartOfAccountList{},
		FundSource:       FundSourceList{},
		DepreciationInfo: &types.DepreciationInfo{},
		TenderInfo:       &types.TenderInfo{},
	}

	// 根据字段索引填充数据，如果字段为空则使用默认值
	for i := 0; i < len(row); i++ {
		field := strings.TrimSpace(row[i])
		switch i {
		case 0:
			combined.AssetBasicInfo.AssetCode = field
		case 1:
			combined.AssetBasicInfo.AssetName = field
		case 2:
			combined.AssetBasicInfo.AssetStatus = field
		case 3:
			if field != "" {
				assetValue, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("资产原值转换错误：%v", err)
				}
				combined.AssetBasicInfo.AssetValue = assetValue
			}
		case 4:
			combined.AssetBasicInfo.AssetSerialNo = field
		case 5:
			combined.AssetBasicInfo.WaysOfChanging = field
		case 6:
			combined.AssetBasicInfo.CountryOfOrigin = field
		case 7:
			combined.AssetBasicInfo.StorageLocation = field
		case 8:
			combined.AssetBasicInfo.RegistrationNo = field
		case 9:
			combined.AssetBasicInfo.DocumentNo = field
		case 10:
			combined.AssetBasicInfo.WarrantyPeriod = field
		case 11:
			combined.AssetBasicInfo.PurchaseDate = field
		case 12:
			combined.AssetBasicInfo.ImportDate = field
		case 13:
			combined.AssetBasicInfo.UseDate = field
		case 14:
			combined.AssetBasicInfo.OriginalAssetCode = field
		case 15:
			combined.AssetBasicInfo.ManageRoom = field
		case 16:
			if field != "" {
				isManyDepartment, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("是否多使用部门转换错误：%v", err)
				}
				combined.AssetBasicInfo.IsManyDepartment = isManyDepartment
			}
		case 17:
			combined.AssetBasicInfo.ManyDepartmentName = field
		case 18:
			combined.AssetBasicInfo.UsageRoom = field
		case 19:
			combined.AssetBasicInfo.AssetOwner = field
		case 20:
			combined.AssetBasicInfo.PositionStandard = field
		case 21:
			combined.AssetBasicInfo.ElectronicTag = field
		case 22:
			combined.AssetBasicInfo.AssetType = field
		case 23:
			combined.AssetBasicInfo.AssetModel = field
		case 24:
			combined.AssetBasicInfo.Brand = field
		case 25:
			combined.AssetBasicInfo.WarrantyCertificateNo = field
		case 26:
			if field != "" {
				paymentAmount, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("付款金额转换错误：%v", err)
				}
				combined.AssetBasicInfo.PaymentAmount = paymentAmount
			}
		case 27:
			if field != "" {

				invoiceAmount, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("发票金额转换错误：%v", err)
				}
				combined.AssetBasicInfo.InvoiceAmount = invoiceAmount
			}
		case 28:
			combined.AssetBasicInfo.InvoiceNo = field
		case 29:
			combined.AssetBasicInfo.ContractNo = field
		case 30:
			combined.AssetBasicInfo.SupplierName = field
		case 31:
			combined.AssetBasicInfo.ManufacturersName = field
		case 32:
			combined.AssetBasicInfo.MaintenanceName = field
		case 33:
			combined.AssetBasicInfo.Unit = field
		case 34:
			if field != "" {
				NetValue, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("当前净值转换错误：%v", err)
				}
				combined.AssetBasicInfo.SlMj = NetValue
			}
		/*	// 处理资产科目副表 ChartOfAccount
			case 34:
				combined.ChartOfAccount.FixedAssetSubjects = field
			case 35:
				combined.ChartOfAccount.DepreciationSubjects = field
			case 36: // 原39
				combined.ChartOfAccount.SubjectName = field
			case 37: // 原41
				combined.ChartOfAccount.UsageRoom = field
			case 38: // 原42
				combined.ChartOfAccount.Percentage = field */

		// FundSource 定义资金来源表副表
		case 35:
			combined.FundSource.SourceAmount1 = field
		case 36:
			combined.FundSource.SourceAmount2 = field
		case 37:
			combined.FundSource.SourceAmount3 = field
		case 38:
			combined.FundSource.SourceAmount4 = field
		case 39:
			combined.FundSource.SourceAmount5 = field
		case 40:
			combined.FundSource.UsageRoom2 = field

			//折旧信息
		case 41:
			combined.DepreciationInfo.StartDate = field
		case 42:
			if field != "" {
				NetValue, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("当前净值转换错误：%v", err)
				}
				combined.DepreciationInfo.NetValue = NetValue
			}
		case 43:
			if field != "" {
				DepreciatedMonths, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("已折旧月份转换错误：%v", err)
				}
				combined.DepreciationInfo.DepreciatedMonths = int32(DepreciatedMonths)
			}
		case 44:
			combined.DepreciationInfo.Method = field
		case 45:
			combined.DepreciationInfo.Remark = field
		case 46:
			if field != "" {
				NetResidueValue, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("净残值转换错误：%v", err)
				}
				combined.DepreciationInfo.NetResidueValue = NetResidueValue
			}
		case 47:
			if field != "" {
				NetResidueRate, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("净残值率转换错误：%v", err)
				}
				combined.DepreciationInfo.NetResidueRate = NetResidueRate
			}
		case 48:
			if field != "" {
				AccumulatedDepreciationValue, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("累计折旧额转换错误：%v", err)
				}
				combined.DepreciationInfo.AccumulatedDepreciationValue = AccumulatedDepreciationValue
			}
		case 49:
			if field != "" {
				NetWorthValue, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("净值转换错误：%v", err)
				}
				combined.DepreciationInfo.NetWorthValue = NetWorthValue
			}
		case 50:
			//预计使用年限
			if field != "" {
				ExpectedUsefulLife, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("使用年份转换错误：%v", err)
				}
				combined.DepreciationInfo.ExpectedUsefulLife = int32(ExpectedUsefulLife)
			}

		case 51:
			combined.TenderInfo.TenderName = field
		case 52:
			combined.TenderInfo.TenderMethod = field
		case 53:
			combined.TenderInfo.TenderForm = field
		case 54:
			combined.TenderInfo.TenderDate = field
		case 55:
			combined.TenderInfo.ContractNumber = field
		case 56:
			combined.TenderInfo.VendorName = field
		case 57:
			if field != "" {
				PurchasePrice, err := safeParseFloat(field)
				if err != nil {
					return nil, fmt.Errorf("购买价格转换错误：%v", err)
				}
				combined.TenderInfo.PurchasePrice = PurchasePrice
			}
		case 58:
			if field != "" {
				PlannedDuration, err := safeParseInt(field)
				if err != nil {
					return nil, fmt.Errorf("计划持续时间(天)转换错误：%v", err)
				}
				combined.TenderInfo.PlannedDuration = int32(PlannedDuration)
			}
		case 59:
			combined.TenderInfo.Remarks = field
		}
	}
	return combined, nil
}

// 将types.DepreciationInfo转换为property_service.DepreciationInfo
func convertToPBDepreciationInfo(info *types.DepreciationInfo) *property_service.DepreciationInfo {
	return &property_service.DepreciationInfo{
		StartDate:                    info.StartDate,
		NetValue:                     info.NetValue,
		UsefulLife:                   info.UsefulLife,
		DepreciatedMonths:            info.DepreciatedMonths,
		StatusName:                   info.StatusName,
		Method:                       info.Method,
		Remark:                       info.Remark,
		NetResidueValue:              info.NetResidueValue,
		NetResidueRate:               info.NetResidueRate,
		AccumulatedDepreciationValue: info.AccumulatedDepreciationValue,
		DepreciationRate:             info.DepreciationRate,
		DepreciationRateYear:         info.DepreciationRateYear,
		NetWorthValue:                info.NetWorthValue,
		NeteValue:                    info.NeteValue,
		StatusID:                     info.StatusID,
		CurrencyId:                   info.CurrencyId,
		CurrencyName:                 info.CurrencyName,
		ExpectedUsefulLife:           info.ExpectedUsefulLife,
		AssetValue:                   info.AssetValue,
		AssetID:                      info.AssetID,
		TenantID:                     info.TenantID,
	}
}

// 将types.TenderInfo转换为property_service.TenderInfo
func convertToPBTenderInfo(info *types.TenderInfo) *property_service.TenderInfo {
	return &property_service.TenderInfo{
		TenderName:      info.TenderName,
		TenderMethod:    info.TenderMethod,
		TenderForm:      info.TenderForm,
		TenderDate:      info.TenderDate,
		ContractNumber:  info.ContractNumber,
		VendorName:      info.VendorName,
		PurchasePrice:   info.PurchasePrice,
		PlannedDuration: info.PlannedDuration,
		Remarks:         info.Remarks,
	}
}

// 将types.AssetBasicInfo转换为property_service.AssetBasicInfo
func convertToPBAssetBasicInfo(info *types.AssetBasicInfo) *property_service.AssetBasicInfo {
	// 创建一个property_service.AssetBasicInfo对象
	return &property_service.AssetBasicInfo{
		AssetCode:             info.AssetCode,
		AssetName:             info.AssetName,
		AssetStatus:           info.AssetStatus,
		AssetCategoryID:       info.AssetCategoryID,
		AssetValue:            info.AssetValue,
		AssetSerialNo:         info.AssetSerialNo,
		WaysOfChanging:        info.WaysOfChanging,
		WaysOfChangingID:      info.WaysOfChangingID,
		CountryOfOrigin:       info.CountryOfOrigin,
		StorageLocation:       info.StorageLocation,
		RegistrationNo:        info.RegistrationNo,
		DocumentNo:            info.DocumentNo,
		PurchaseDate:          info.PurchaseDate,
		WarrantyPeriod:        info.WarrantyPeriod,
		ImportDate:            info.ImportDate,
		UseDate:               info.UseDate,
		OriginalAssetCode:     info.OriginalAssetCode,
		AssetStatusFlag:       info.AssetStatusFlag,
		ManageRoom:            info.ManageRoom,
		IsManyDepartment:      info.IsManyDepartment,
		UsageRoom:             info.UsageRoom,
		UsageRoomID:           info.UsageRoomID,
		AssetOwner:            info.AssetOwner,
		PositionStandard:      info.PositionStandard,
		ElectronicTag:         info.ElectronicTag,
		AssetType:             info.AssetType,
		AssetModel:            info.AssetModel,
		Brand:                 info.Brand,
		WarrantyCertificateNo: info.WarrantyCertificateNo,
		PaymentAmount:         info.PaymentAmount,
		InvoiceAmount:         info.InvoiceAmount,
		InvoiceNo:             info.InvoiceNo,
		ContractNo:            info.ContractNo,
		SupplierName:          info.SupplierName,
		SupplierID:            info.SupplierID,
		MaintenanceName:       info.MaintenanceName,
		ManufacturersName:     info.ManufacturersName,
		ManufacturerCodeID:    info.ManufacturerCodeID,
		MaintenanceID:         info.MaintenanceID,
		Unit:                  info.Unit,
		// 其他字段...
	}
}

func convertToPBChartOfAccount(coa ChartOfAccountList) []*property_service.ChartOfAccount {
	// 获取各个字段的切片表示
	fixedAssetSubjects := strings.Split(coa.FixedAssetSubjects, ";")
	depreciationSubjects := strings.Split(coa.DepreciationSubjects, ";")
	SubjectNames := strings.Split(coa.SubjectName, ";")
	usageRooms := strings.Split(coa.UsageRoom, ";")
	percentages := strings.Split(coa.Percentage, ";")

	// 确定最大长度以遍历所有数据
	maxLen := 0
	for _, arr := range [][]string{fixedAssetSubjects, depreciationSubjects, SubjectNames, usageRooms, percentages} {
		if len(arr) > maxLen {
			maxLen = len(arr)
		}
	}

	// 构建 property_service.ChartOfAccount 对象数组
	var pbCOA []*property_service.ChartOfAccount
	for i := 0; i < maxLen; i++ {
		// 获取当前索引对应的值
		fixedAssetIDStr := getValueAtIndex(fixedAssetSubjects, i)
		depreciationID := getValueAtIndex(depreciationSubjects, i)
		SubjectName := getValueAtIndex(SubjectNames, i)
		usageRoom := getValueAtIndex(usageRooms, i)

		percentage, err := safeParseFloat(getValueAtIndex(percentages, i))
		if err != nil {
			err.Error()
		}

		pbCOA = append(pbCOA, &property_service.ChartOfAccount{
			FixedAssetSubjectsName:   fixedAssetIDStr,
			DepreciationSubjectsName: depreciationID,
			SubjectName:              SubjectName,
			UsageRoom:                usageRoom,
			Percentage:               percentage,
		})
	}

	return pbCOA
}

func convertToPBFundSource(fs FundSourceList) []*property_service.FundSource {
	// 获取各个字段的切片表示
	sourceAmount1 := strings.Split(fs.SourceAmount1, ";")
	sourceAmount2 := strings.Split(fs.SourceAmount2, ";")
	sourceAmount3 := strings.Split(fs.SourceAmount3, ";")
	sourceAmount4 := strings.Split(fs.SourceAmount4, ";")
	sourceAmount5 := strings.Split(fs.SourceAmount5, ";")
	usageRoom2 := strings.Split(fs.UsageRoom2, ";")

	// 确定最大长度以遍历所有数据
	maxLen := 0
	for _, arr := range [][]string{sourceAmount1, sourceAmount2, sourceAmount3, sourceAmount4, sourceAmount5, usageRoom2} {
		if len(arr) > maxLen {
			maxLen = len(arr)
		}
	}

	// 构建 property_service.FundSource 对象数组
	var pbFS []*property_service.FundSource
	for i := 0; i < maxLen; i++ {
		// 获取当前索引对应的值
		amount1, err := safeParseInt(getValueAtIndex(sourceAmount1, i))
		if err != nil {
			err.Error()
		}

		amount2, err := safeParseInt(getValueAtIndex(sourceAmount2, i))
		if err != nil {
			err.Error()
		}

		amount3, err := safeParseInt(getValueAtIndex(sourceAmount3, i))
		if err != nil {
			err.Error()
		}

		amount4, err := safeParseInt(getValueAtIndex(sourceAmount4, i))
		if err != nil {
			err.Error()
		}

		amount5, err := safeParseInt(getValueAtIndex(sourceAmount5, i))
		if err != nil {
			err.Error()
		}

		usageRoom := getValueAtIndex(usageRoom2, i)

		pbFS = append(pbFS, &property_service.FundSource{
			SourceAmount1: amount1,
			SourceAmount2: amount2,
			SourceAmount3: amount3,
			SourceAmount4: amount4,
			SourceAmount5: amount5,
			UsageRoom:     usageRoom,
		})
	}

	return pbFS
}

// getValueAtIndex 是一个辅助函数，用于安全地获取指定索引位置的值。
// 如果索引超出范围，则返回空字符串。
func getValueAtIndex(arr []string, index int) string {
	if index >= 0 && index < len(arr) {
		return arr[index]
	}
	return ""
}

// safeParseInt函数用于将字符串转换为int64类型，如果字符串为空，则返回0和nil
func safeParseInt(s string) (int64, error) {
	// 如果字符串为空，则返回0和nil
	if s == "" {
		return 0, nil
	}
	//如果后面有千位符则去除
	s = strings.ReplaceAll(s, ",", "")
	f, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return 0, nil
	}
	return int64(f), nil
}

// safeParseFloat函数用于将字符串转换为浮点数，如果字符串为空，则返回0和nil
func safeParseFloat(s string) (float64, error) {
	// 如果字符串为空，则返回0和nil
	if s == "" {
		return 0, nil
	}
	//如果后面有千位符则去除
	s = strings.ReplaceAll(s, ",", "")
	// 否则，使用strconv.ParseFloat函数将字符串转换为浮点数
	return strconv.ParseFloat(s, 64)
}

// ChaXunSupplierLevelAddition 函数用于查询指定供应商的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunSupplierLevelAddition(s string, TenantID int64) (int64, string) {
	// l.Logger.Infof("查询供应商级别: Name=%s, TenantID=%d", s, TenantID)

	res, err := l.svcCtx.BasicService.SupplierLevelAdditionPage(l.ctx, &property_service.SupplierLevelAdditionPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.SupplierLevelAddition{
			SupplierLevelName: s,
			IsMc:              1,
			TenantID:          TenantID,
		},
	})
	if err != nil {
		l.Logger.Errorf("查询供应商级别失败: %v", err)
		return 0, "查询异常"
	}

	// l.Logger.Infof("查询供应商级别结果: Count=%d", res.Count)

	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			l.Logger.Errorf("查询到多个供应商级别: Name=%s, Count=%d", s, len(res.List))
			return 0, "查询到多项"
		}
		// l.Logger.Infof("成功查询供应商级别: Name=%s, ID=%d", s, res.List[0].ID)
		return res.List[0].ID, ""
	}

	l.Logger.Errorf("未找到供应商级别: Name=%s", s)
	return 0, "未找到"
}

// ChaXunDictionaryDetail 函数用于查询指定字典详情的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunDictionaryDetail(DictKey string, ItemValue string, TenantID int64) (string, string) {
	// l.Logger.Infof("查询字典详情: DictKey=%s, ItemKey=%s, TenantID=%d", DictKey, ItemKey, TenantID)

	res, err := l.svcCtx.BasicService.DictionaryDetailPage(l.ctx, &property_service.DictionaryDetailPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.DictionaryDetail{
			DictKey:   DictKey,
			ItemValue: ItemValue,
			TenantID:  TenantID,
		},
	})
	if err != nil {
		l.Logger.Errorf("查询字典详情失败: %v", err)
		return "", fmt.Sprintf("查询字典详情失败: %s", err.Error())
	}

	// l.Logger.Infof("查询字典详情结果: Count=%d", res.Count)

	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			l.Logger.Errorf("查询到多个字典详情项: DictKey=%s, ItemValue=%s, Count=%d", DictKey, ItemValue, len(res.List))
			return "", "查询到多项"
		}
		// l.Logger.Infof("成功查询字典详情: DictKey=%s, ItemKey=%s, ItemValue=%s", DictKey, ItemKey, res.List[0].ItemValue)
		return res.List[0].ItemKey, ""
	}
	sc := fmt.Sprintf("未找到字典详情: DictKey=%s, ItemValue=%s", DictKey, ItemValue)
	l.Logger.Error(sc)
	return "", fmt.Sprintf("未找到字典详情: DictKey=%s, ItemValue=%s", DictKey, ItemValue)
}

// ChaXunSupplierCertType 函数用于查询厂商的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunSupplierCertType(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.SupplierCertTypePage(l.ctx, &property_service.SupplierCertTypePageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.SupplierCertType{
			CertificateName: s, //这里假设你想要查询的列是CertificateName
			IsMc:            1,
			TenantID:        TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	l.Logger.Error(fmt.Sprintf("厂商未找到: Name: %s   TenantID: %d   ", s, TenantID))
	return 0, "厂商未找到"
}

// ChaXunBrandAddition 函数用于查询指定品牌附加的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunBrandAddition(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.BrandAdditionPage(l.ctx, &property_service.BrandAdditionPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.BrandAddition{
			BrandName: s,
			IsMc:      1,
			TenantID:  TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	l.Logger.Error(fmt.Sprintf("品牌未找到: Name: %s   TenantID: %d   ", s, TenantID))
	return 0, "未找到"
}

// ChaXunContractMain 函数用于查询指定合同主表的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunContractMain(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.ContractMainPage(l.ctx, &property_service.ContractMainPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.ContractMain{
			ContractName: s,
			IsMc:         1,
			TenantID:     TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	sc := fmt.Sprintf("合同未找到: Name: %s   TenantID: %d   ", s, TenantID)
	l.Logger.Error(sc)
	return 0, "未找到"
}

// ChaXunFinanceAccountSubject 函数用于查询指定财务科目的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunFinanceAccountSubject(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.FinanceAccountSubjectPage(l.ctx, &property_service.FinanceAccountSubjectPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.FinanceAccountSubject{
			SubjectName: s,
			IsMc:        1,
			TenantID:    TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	sc := fmt.Sprintf("财务科目未找到: Name: %s   TenantID: %d   ", s, TenantID)
	l.Logger.Error(sc)
	return 0, "未找到"
}

// ChaXunHospitalDepartment 函数用于查询指定医院科室的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunHospitalDepartment(s string, TenantID int64) (*property_service.HospitalDepartment, string) {
	res, err := l.svcCtx.BasicService.HospitalDepartmentPage(l.ctx, &property_service.HospitalDepartmentPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.HospitalDepartment{
			Name:     s,
			IsMc:     1,
			TenantID: TenantID,
		},
	})
	if err != nil {
		return nil, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return nil, "查询到多项"
		}
		return res.List[0], ""
	}
	sc := fmt.Sprintf("医院科室未找到: Name: %s   TenantID: %d   ", s, TenantID)
	l.Logger.Error(sc)
	return nil, "未找到"
}

// ChaXunAssetType 函数用于查询指定资产分类的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunAssetType(s string, TenantID int64) (*property_service.AssetType, string) {
	res, err := l.svcCtx.BasicService.AssetTypePage(l.ctx, &property_service.AssetTypePageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.AssetType{
			Name:     s,
			IsMc:     1,
			TenantID: TenantID,
		},
	})
	if err != nil {
		return nil, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return nil, "查询到多项"
		}
		return res.List[0], ""
	}
	sc := fmt.Sprintf("资产类型未找到: Name: %s   TenantID: %d   ", s, TenantID)
	l.Logger.Error(sc)
	return nil, "未找到"
}

// ChaXunAssetCategory 函数用于查询指定资产类别的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunAssetCategory(s string, vd string, TenantID int64) (*property_service.AssetCategory, string) {
	res, err := l.svcCtx.BasicService.AssetCategoryPage(l.ctx, &property_service.AssetCategoryPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.AssetCategory{
			Name:          s,
			AssetTypeName: vd,
			IsMc:          1,
			TenantID:      TenantID,
		},
	})
	if err != nil {
		return nil, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return nil, "查询到多项"
		}
		return res.List[0], ""
	}
	sc := fmt.Sprintf("资产分类未找到: Name: %s   AssetTypeName: %s TenantID: %d   \n", s, vd, TenantID)
	l.Logger.Error(sc)
	return nil, "未找到"
}

// ChaXunCountryOfOrigin 函数用于查询指定产地的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunCountryOfOrigin(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.OriginAdditionPage(l.ctx, &property_service.OriginAdditionPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.OriginAddition{
			OriginName: s,
			TenantID:   TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	//如果输入为空，则返回0和"未找到"
	return 0, "未找到"
}

// ChaXunVendorInfo 函数用于查询指定供应商的ID，如果找到多个结果，则返回错误。
func (l *UploadLogic) ChaXunVendorInfo(s string, TenantID int64) (int64, string) {
	res, err := l.svcCtx.BasicService.VendorInfoPage(l.ctx, &property_service.VendorInfoPageReq{
		Page:  0,
		Limit: 0,
		Where: &property_service.VendorInfo{
			Name:     s,
			IsMc:     1,
			TenantID: TenantID,
		},
	})
	if err != nil {
		return 0, "查询异常"
	}
	if res.List != nil && len(res.List) > 0 {
		if len(res.List) > 1 {
			return 0, "查询到多项"
		}
		return res.List[0].ID, ""
	}
	return 0, "未找到"
}

// DuoXian 是一个处理多线资产信息的方法
// 它接收一个CombinedAssetInfo类型的切片作为参数
// 返回两个值：Msg报错字符串切片和成功数组AssetBasicInfo类型的指针切片
func (l *UploadLogic) DuoXian(dq int, stockID int64, tenantID int64, ctx context.Context, combinedList []*CombinedAssetInfo, StatusDisposition *property_service.StatusDisposition) (Msgs []string, AssetBasicInfos []*property_service.AssetBasicInfo) {
	for x, combined := range combinedList {
		//储存当前报错
		MsgS := ""
		//查询资产基础信息的 id
		AssetBasicInfo := convertToPBAssetBasicInfo(combined.AssetBasicInfo)
		//处理需要查询的数据
		AssetBasicInfo.TenantID = tenantID

		//设置默认状态
		AssetBasicInfo.StatusID = StatusDisposition.ID
		AssetBasicInfo.StatusName = StatusDisposition.StatusName

		//通过分类名称返回资产分类
		AssetCategory, mss := l.ChaXunAssetCategory(AssetBasicInfo.AssetName, AssetBasicInfo.AssetType, tenantID)
		if AssetCategory != nil {
			//赋值资产分类名称
			AssetBasicInfo.AssetCategory = AssetCategory.Name
			//储存当前ID
			AssetBasicInfo.AssetCategoryID = AssetCategory.ID
			//赋值资产类型
			AssetBasicInfo.AssetType = AssetCategory.AssetTypeName
			//赋值资产类型ID
			AssetBasicInfo.AssetTypeID = AssetCategory.AssetTypeID
		} else {
			//异常
			MsgS = fmt.Sprintf(" %s 资产分类：%s", MsgS, mss)
		}

		//变动方式
		if AssetBasicInfo.WaysOfChanging != "" {
			key, mss := l.ChaXunDictionaryDetail("CHANGE_MODE", AssetBasicInfo.WaysOfChanging, tenantID)
			//改变方式
			if key != "" {
				AssetBasicInfo.WaysOfChangingID = key
			} else {
				//异常
				MsgS = fmt.Sprintf(" %s 变动方式：%s", MsgS, mss)
			}
		}

		//使用状态
		if AssetBasicInfo.AssetStatus != "" {
			key, mss := l.ChaXunDictionaryDetail("STATUS", AssetBasicInfo.AssetStatus, tenantID)
			if key != "" {
				AssetBasicInfo.AssetStatusFlag = key
			} else {
				//异常
				MsgS = fmt.Sprintf(" %s 使用状态：%s", MsgS, mss)
			}
		}

		//产地去查找表
		if AssetBasicInfo.CountryOfOrigin != "" {
			id, mss := l.ChaXunCountryOfOrigin(AssetBasicInfo.CountryOfOrigin, tenantID)
			if id != 0 {
				AssetBasicInfo.CountryOfOriginID = id
			} else {
				//异常
				MsgS = fmt.Sprintf(" %s 产地信息：%s", MsgS, mss)
			}
		}

		//管理科室
		if AssetBasicInfo.ManageRoom != "" {
			ks, mss := l.ChaXunHospitalDepartment(AssetBasicInfo.ManageRoom, tenantID)
			if ks != nil {
				AssetBasicInfo.ManageRoomID = ks.ID
				AssetBasicInfo.ManageRoom = ks.Name
			} else {
				//异常
				MsgS = fmt.Sprintf("%s  管理科室：%s", MsgS, mss)
			}
		}

		if AssetBasicInfo.ManyDepartmentName != "" {
			//1.多使用科室名称
			var MultiDepartmentNames []string = strings.Split(AssetBasicInfo.ManyDepartmentName, ";")
			// 2. 遍历数组并查询每个科室的 ID
			var departmentIDs []string
			for _, name := range MultiDepartmentNames {
				ks, mss := l.ChaXunHospitalDepartment(name, tenantID)
				if ks == nil { //异常
					MsgS = fmt.Sprintf(" %s 多科室名称：%s", MsgS, mss)
				} else {
					departmentIDs = append(departmentIDs, strconv.FormatInt(ks.ID, 10)) // 将 int64 转换为 string 并加入结果切片
				}

			}
			//3.多使用科室ID
			AssetBasicInfo.ManyDepartmentID = strings.Join(departmentIDs, ";")
		}

		//使用科室ID
		if AssetBasicInfo.UsageRoom != "" {
			ks, mss := l.ChaXunHospitalDepartment(AssetBasicInfo.UsageRoom, tenantID)

			if ks != nil {
				AssetBasicInfo.UsageRoomID = ks.ID
				AssetBasicInfo.UsageRoom = ks.Name
			} else {
				//异常
				MsgS = fmt.Sprintf(" %s 使用科室异常：%s", MsgS, mss)
			}
		}

		/*		//资产类型  通过资产分类进行查询赋值
				AssetType, mss := l.ChaXunAssetType(AssetBasicInfo.AssetType, tenantID)
				if AssetType != nil {
					//储存当前ID
					AssetBasicInfo.AssetTypeID = AssetType.ID
				} else {
					//异常
					MsgS = fmt.Sprintf("%s 资产类型：%s", MsgS, mss)
				}*/

		//品牌 信息
		if AssetBasicInfo.Brand != "" {
			id, mss := l.ChaXunBrandAddition(AssetBasicInfo.Brand, tenantID)
			if id != 0 {
				AssetBasicInfo.BrandID = id
			} else {
				//异常
				MsgS = fmt.Sprintf("%s  品牌信息：%s", MsgS, mss)
			}
		}

		//供应商信息
		if AssetBasicInfo.SupplierName != "" {
			id, mss := l.ChaXunSupplierLevelAddition(AssetBasicInfo.SupplierName, tenantID)
			if id != 0 {
				AssetBasicInfo.SupplierID = id
			} else {
				//异常
				MsgS = fmt.Sprintf("%s  供应商信息：%s", MsgS, mss)
			}
		}

		//生产商
		if AssetBasicInfo.ManufacturersName != "" {
			id, mss := l.ChaXunVendorInfo(AssetBasicInfo.ManufacturersName, tenantID)
			if id != 0 {
				AssetBasicInfo.ManufacturersID = id
			} else {
				//异常
				MsgS = fmt.Sprintf("%s 生产商：%s", MsgS, mss)
			}
		}

		//维保商
		if AssetBasicInfo.MaintenanceName != "" {
			id, mss := l.ChaXunVendorInfo(AssetBasicInfo.MaintenanceName, tenantID)
			if id != 0 {
				AssetBasicInfo.MaintenanceID = id
			} else {
				//异常
				MsgS = fmt.Sprintf("%s 维保商：%s", MsgS, mss)
			}
		}
		//如果有找不到资料的，则不进行添加，将错误添加至集合，批处理
		if MsgS != "" {
			cc := dq + x + 2 //数组从0开始，第一行为标题 所以需要加2
			//后台输出
			MsgS = fmt.Sprintf(" \n 第%d行资产信息%s存在问题: %s", cc, AssetBasicInfo.AssetName, MsgS)
			fmt.Println(MsgS)
			Msgs = append(Msgs, MsgS)
		} else {
			//将没有问题的数据添加到集合中
			//仓库id
			AssetBasicInfo.StockID = stockID
			//设置TenantID
			AssetBasicInfo.TenantID = tenantID
			// 插入资产基础信息
			res, err := l.svcCtx.AssetService.AssetBasicInfoAdd(ctx, AssetBasicInfo)
			AssetBasicInfos = append(AssetBasicInfos, AssetBasicInfo)

			// 获取添加后的资产ID
			AssetID := res.Id
			if err != nil {
				err.Error()
			}

			// 插入资金来源
			var FundSources = convertToPBFundSource(combined.FundSource)
			for _, fs := range FundSources {
				//设置仓库
				fs.AssetID = AssetID
				//设置TenantID
				fs.TenantID = tenantID
				_, err := l.svcCtx.AssetService.FundSourceAdd(ctx, fs)
				if err != nil {
					err.Error()
				}
			}

			//如果未找到分类信息，则不处理折旧信息
			if AssetCategory != nil {
				// 插入折旧信息
				DepreciationInfo := combined.DepreciationInfo
				DepreciationInfo.AssetID = AssetID
				//设置资产原值
				DepreciationInfo.AssetValue = AssetBasicInfo.AssetValue
				//计算月折旧率：(1-净残值率*100)/使用年限(月) = 月折旧率
				f := ((1 - DepreciationInfo.NetResidueRate) * 100) / float64(DepreciationInfo.ExpectedUsefulLife)
				//计算	剩余年限 = 预计使用年限(月) - 已折旧月份
				DepreciationInfo.UsefulLife = DepreciationInfo.ExpectedUsefulLife - DepreciationInfo.DepreciatedMonths
				//月折旧率
				DepreciationInfo.DepreciationRate = f
				//设置默认币种
				key, mss := l.ChaXunDictionaryDetail("CURRENCY", "RMB", tenantID)
				//改变方式
				if key != "" {
					DepreciationInfo.CurrencyName = "RMB"
					DepreciationInfo.CurrencyId = key
				} else {
					//异常
					MsgS = fmt.Sprintf(" %s 币种：%s", MsgS, mss)
				}
				//设置默认折旧方式
				DepreciationInfo.Method = "平均年限法"
				//计算年折旧率
				DepreciationInfo.DepreciationRateYear = f * 12
				//设置TenantID
				DepreciationInfo.TenantID = tenantID
				//已折旧年份是否等于资产年限
				if DepreciationInfo.DepreciatedMonths == DepreciationInfo.ExpectedUsefulLife {
					DepreciationInfo.StatusID = 1
					DepreciationInfo.StatusName = "已报废"
				} else {
					DepreciationInfo.StatusID = 0
					DepreciationInfo.StatusName = "正常折旧"
				}
				//获取资产类型
				_, err = l.svcCtx.AssetService.DepreciationInfoAdd(ctx, convertToPBDepreciationInfo(DepreciationInfo))
				if err != nil {
					//异常
					MsgS = fmt.Sprintf(" %s 插入折旧信息报错：%s", MsgS, err.Error())
					err.Error()
				}
			} else {
				//异常
				MsgS = fmt.Sprintf(" %s 资产分类：%s", MsgS, mss)
			}

			// 插入招标信息
			combined.TenderInfo.AssetID = AssetID
			//设置TenantID
			combined.TenderInfo.TenantID = tenantID
			_, err = l.svcCtx.AssetService.TenderInfoAdd(ctx, convertToPBTenderInfo(combined.TenderInfo))
			if err != nil {
				err.Error()
			}
		}
	}
	return Msgs, AssetBasicInfos
}

// 保留 n 位小数
func Round(f float64, n int) float64 {
	pow := math.Pow(10, float64(n))
	return math.Round(f*pow) / pow
}
